package com.chase.springboot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chase.springboot.mapper.TopicMapper;
import com.chase.springboot.mapper.UserMapper;
import com.chase.springboot.model.dto.PostDTO;
import com.chase.springboot.model.entity.Tag;
import com.chase.springboot.service.IPostService;
import com.chase.springboot.service.ITagService;
import com.chase.springboot.service.ITopicTagService;
import com.chase.springboot.service.IUserService;
import com.chase.springboot.mapper.TagMapper;
import com.chase.springboot.model.dto.CreateTopicDTO;
import com.chase.springboot.model.entity.Post;
import com.chase.springboot.model.entity.TopicTag;
import com.chase.springboot.model.entity.User;
import com.chase.springboot.model.vo.PostVO;
import com.chase.springboot.model.vo.ProfileVO;
import com.vdurmont.emoji.EmojiParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.Supplier;
import java.util.stream.Collectors;


@Service
public class PostServiceImpl extends ServiceImpl<TopicMapper, Post> implements IPostService {
    @Resource
    private TagMapper tagMapper;
    @Resource
    private UserMapper userMapper;

//    @Resource
//    private TopicMapper topicMapper;

    @Autowired
    @Lazy
    private ITagService iTagService;

    @Autowired
    private IUserService iUserService;

    @Autowired
    private ITopicTagService iTopicTagService;


    private ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10,
            0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>());

    @Override
    public Page<PostVO> getList(Page<PostVO> page, String tab) throws ExecutionException, InterruptedException {
        //用线程串行化获取列表数据
        CompletableFuture<Page<PostVO>> future = CompletableFuture.supplyAsync(() -> {
            // 查询话题
            Page<PostVO> iPage = this.baseMapper.selectListAndPage(page, tab);
            return iPage;
        }, executor).thenApplyAsync(res -> {
            // 添加标签
            setTopicTags(res);
            return res;
        }, executor);
        return future.get();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Post create(CreateTopicDTO dto, User user) {
        Post topic1 = this.baseMapper.selectOne(new LambdaQueryWrapper<Post>().eq(Post::getTitle, dto.getTitle()));
        Assert.isNull(topic1, "话题已存在，请修改");

        // 封装
        Post topic = Post.builder()
                .userId(user.getId())
                .title(dto.getTitle())
                .content(EmojiParser.parseToAliases(dto.getContent()))
                .createTime(new Date())
                .build();
        this.baseMapper.insert(topic);

        // 用户积分增加
        int newScore = user.getScore() + 1;
        userMapper.updateById(user.setScore(newScore));

        // 标签
        if (!ObjectUtils.isEmpty(dto.getTags())) {
            // 保存标签
            List<Tag> tags = iTagService.insertTags(dto.getTags());
            // 处理标签与话题的关联
            iTopicTagService.createTopicTag(topic.getId(), tags);
        }

        return topic;
    }

    @Override
    public Map<String, Object> viewTopic(String id) {
        Map<String, Object> map = new HashMap<>(16);
        Post topic = this.baseMapper.selectById(id);
        Assert.notNull(topic, "当前话题不存在,或已被作者删除");
        // 查询话题详情
        topic.setView(topic.getView() + 1);
        this.baseMapper.updateById(topic);
        // emoji转码
        topic.setContent(EmojiParser.parseToUnicode(topic.getContent()));
        map.put("topic", topic);
        // 标签
        QueryWrapper<TopicTag> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(TopicTag::getTopicId, topic.getId());
        Set<String> set = new HashSet<>();
        for (TopicTag articleTag : iTopicTagService.list(wrapper)) {
            set.add(articleTag.getTagId());
        }
        List<Tag> tags = new ArrayList<>();
        if (set.size() > 0){
            tags = iTagService.listByIds(set);
        }
        map.put("tags", tags);

        // 作者
        ProfileVO user = iUserService.getUserProfile(topic.getUserId());
        map.put("user", user);

        return map;
    }

    @Override
    public List<Post> getRecommend(String id) {
        return this.baseMapper.selectRecommend(id);
    }
    @Override
    public Page<PostVO> searchByKey(String keyword, Page<PostVO> page) {
        // 查询话题
        System.out.println(keyword);
        Page<PostVO> iPage = this.baseMapper.searchByKey(page, keyword);
        // 查询话题的标签
        setTopicTags(iPage);
        return iPage;
    }

    @Override
    public Post updatePostAndTag(PostDTO postDTO) {
        Post post = new Post(postDTO.getId(), postDTO.getTitle(), postDTO.getContent(),postDTO.getUserId(),
                postDTO.getComments(),postDTO.getCollects(),postDTO.getView(),postDTO.getSectionId(),postDTO.getTop(),
                postDTO.getEssence(),postDTO.getCreateTime(),postDTO.getModifyTime(),postDTO.getIsDeleted());
        boolean b = this.updateById(post);
        //删除该文章的Tag...
        //删除TopicTag的关联
        int i = iTopicTagService.deleteByTopicId(postDTO.getId());
        //将Tag保存
        List<Tag> tags = iTagService.insertTags(postDTO.getTagIds());
        //添加Topic和Tag的关联
        iTopicTagService.createTopicTag(postDTO.getId(), tags);
        System.out.println(b + " " + i);
        return post;
    }

    private void setTopicTags(Page<PostVO> iPage) {
        iPage.getRecords().forEach(topic -> {
            List<TopicTag> topicTags = iTopicTagService.selectByTopicId(topic.getId()); //通过文章id获取（文章标签列表）
            if (!topicTags.isEmpty()) {
                List<String> tagIds = topicTags.stream().map(TopicTag::getTagId).collect(Collectors.toList());//获取文章对应的所有标签id
                List<Tag> tags = tagMapper.selectBatchIds(tagIds);    //通过标签id获取标签实体
                topic.setTags(tags);
            }
        });
    }
}
